/**
 * #### 用于将一个数从一个范围映射到另一个范围
 * @param n 数字
 * @param in_range 参照范围
 * @param out_range 目标范围
 * @returns number
 */
export function rangeScale(
  // n：要映射的数
  n: number,
  // in_range：输入范围，是一个数组，包含两个数，分别表示输入范围的最小值和最大值
  in_range: [number, number],
  // out_range：输出范围，是一个数组，包含两个数，分别表示输出范围的最小值和最大值
  out_range: [number, number]
) {
  const min = Math.min(in_range[0], in_range[1]);
  const max = Math.max(in_range[0], in_range[1]);
  // 将n限制在输入范围之内，如果n小于输入范围的最小值，则返回最小值，如果n大于输入范围的最大值，则返回最大值
  const num = Math.max(Math.min(n, max), min);
  // 将num映射到输出范围之内，返回映射后的值
  const out_min = Math.min(out_range[0], out_range[1]);
  const out_max = Math.max(out_range[0], out_range[1]);
  return ((num - min) / (max - min)) * (out_max - out_min) + out_min;
}

/**
 * #### 随机正整数
 * @param min 最小值
 * @param max 最大值
 * @param isInclusiveMax 是否包含最大值，默认为包含 true
 * @returns
 */
export function randomInt(min: number, max: number, isInclusiveMax = true) {
  return (
    Math.floor(Math.random() * (max - min + (isInclusiveMax ? 1 : 0))) + min
  );
}

/**
 * #### 根据精度判断两浮点数是否相等
 * @param a 浮点数a
 * @param b 浮点数b
 * @param precision 精度，默认为2
 * @returns
 */
export function floatEqual(a: number, b: number, precision = 2) {
  const epsilon = Math.pow(10, -precision);
  return Math.abs(a - b) < epsilon;
}

/**
 * #### 判断一个数是否是2的幂
 * @param n 数字
 * @returns booean
 */
export function isPowerOfTwo(n: number) {
  return n > 0 && (n & (n - 1)) === 0;
}

/**
 * #### 判断两个数字是否同号
 * @param n1
 * @param n2
 * @returns boolean
 */
export function isSameSign(n1: number, n2: number) {
  return n1 * n2 >= 0;
}

/**
 * #### 判断一个数是否是奇数
 * @param n 数字
 * @returns
 */
export function isOdd(n: number) {
  return n % 2 === 1 || n % 2 === -1;
}

/**
 * #### 快速计算平方根
 * @param n 数字
 * @returns
 */
export function fastSqrt(n: number) {
  // 计算n的一半
  const xHalf = 0.5 * n;
  // 将n转换为BigInt64Array类型
  let i = new BigInt64Array(new Float32Array([n]).buffer)[0];
  // 将i右移一位，并加上0x1ff7a3bea91d9b1bn
  i = 0x1ff7a3bea91d9b1bn + (i >> 1n);
  // 将i转换为Float64Array类型
  let f = new Float64Array(new BigInt64Array([i]).buffer)[0];
  // 计算f的平方根
  f = f * 0.5 + xHalf / f;
  f = f * 0.5 + xHalf / f;
  f = f * 0.5 + xHalf / f;
  // 返回f的平方根
  return f;
}

/**
 * #### 计算两个数的中间值
 * @param a 数字a
 * @param b 数字b
 * @returns
 */
export const middleNum = (a: number, b: number) => b - ((b - a) >> 1);

/**
 * #### 计算两个数的最大公约数
 * @param a 数字a
 * @param b 数字b
 * @returns
 */
export function calcGCD(a: number, b: number) {
  // 如果b为0，则返回a
  if (b === 0) return a;
  // 否则，递归调用getGCD函数，参数为b和a除以b的余数
  return calcGCD(b, a % b);
}

/**
 * #### 计算两个数的最小公倍数
 * @param a 数字a
 * @param b
 * @returns
 */
export function calcLCM(a: number, b: number) {
  return (a * b) / calcGCD(a, b);
}

export const pow = (n: number) => n ** 2;

export function sheetColumnToNumber(col: string) {
  if (!col) return 0;
  let result = 0;
  for (let i = 0, len = col.length; i < len; i++) {
    result = result * 26 + (col.charCodeAt(i) - "A".charCodeAt(0)) + 1;
  }
  return result;
}
